using System;
using System.Collections.Generic;
using Castle.ActiveRecord;
using Castle.Components.Validator;

namespace ValidationFramework.ActiveRecord
{
    /// <summary>
    /// Base class that provides minimal validation logic.
    /// </summary>
    [Serializable]
    public abstract class ActiveRecordValidatableBase<T> : ActiveRecordBase<T>, NHibernate.Classic.IValidatable, IValidatable
    {



        #region Properties


        /// <summary>
        /// An <see cref="object"/> to pass as the context parameter when calling <see cref="Rule.Validate"/>. The default is null.
        /// </summary>
        public virtual object Context
        {
            get
            {
                return PropertyValidationManager.Context;
            }
			set
			{
				PropertyValidationManager.Context = value;
			}
        }

        /// <summary>
        /// Gets the rule set to validate.
        /// </summary>
        /// <remarks>Will be a null to validate all <see cref="Rule"/>s.</remarks>
		public virtual string RuleSet
        {
            get
            {
                return PropertyValidationManager.RuleSet;
            }
        }
        /// <summary>
        /// Gets a <see cref="IList{T}"/> containing all <see cref="ValidationError"/> in error.
        /// </summary>
        public virtual IList<ValidationError> ValidatorResultsInError
        {
            get
            {
                return PropertyValidationManager.ValidatorResultsInError;
            }
        }

        /// <summary>
        /// Gets the <see cref="ValidationFramework.PropertyValidationManager"/>.
        /// </summary>
		public virtual MemberValidationManager PropertyValidationManager
        {
        	get;
        	private set;
        }

        /// <summary>
        /// Gets a <see lanword="bool"/> indicating if the current state is valid.
        /// </summary>
        /// <remarks>
        /// Base behavior is to validate all properties and return boolean value.
        /// Sub-class can override this if, for example, they are validating on the fly.
        /// </remarks>
        public virtual bool IsValid
        {
            get
            {
                    PropertyValidationManager.ValidateAll();
                return PropertyValidationManager.IsValid;
            }
        }


        /// <summary>
        /// Gets a <see see="IList{T}"/> of <see langword="string"/>s that contain all the error messages.
        /// </summary>
        public virtual IList<string> ErrorMessages
        {
            get
            {
                return ResultFormatter.GetErrorMessages(PropertyValidationManager.ValidatorResultsInError);
            }
        }


     
        #endregion


        #region Methods

        /// <summary>
        /// Throws an exception explaining why the save or update cannot be executed when fields are not ok to pass.
        /// </summary>
        /// <exception cref="ValidationException"><see cref="IsValid"/> is <c>false</c>.</exception>
        void NHibernate.Classic.IValidatable.Validate()
        {
            if (!IsValid)
            {
                var errorsList = new List<string>(ErrorMessages);
                throw new ValidationException(
                    "Can't save or update as there is one (or more) field that has not passed the validation test",
                    errorsList.ToArray());
            }
        }

        #endregion
    }
}